package reflex.learning02;

import org.junit.Test;
import reflex.learning01.ClothFactory;
import reflex.learning01.NickClothFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @program JavaBase
 * @description: 动态代理
 * @author: zhanglu
 * @create: 2019-06-08 15:10:00
 */

interface Subject{
    void action();

    int count();
}

//被代理类
class RealSubject implements Subject{

    @Override
    public void action() {
        System.out.println("我是被代理类");
    }

    @Override
    public int count() {
        return 10;
    }
}

//被代理类
class RealSubject2 implements Subject{

    @Override
    public void action() {
        System.out.println("我是被代理类2");
    }

    @Override
    public int count() {
        return 10;
    }
}


/**
 * 动态代理相关
 */
class MyInvocationHandler implements InvocationHandler{

    Object obj; //实现了接口的被代理类的对象的声明

    /**
     * - 给被代理类的对象实例化
     * - 返回一个代理类的对象
     */
    public Object blind(Object obj){
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    /**
     * 当通过代理类的对象发起对被重写的方法的调用时，都会转化为对如下的invoke方法的调用
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method方法的返回值
        Object res =  method.invoke(obj, args);
        return res;
    }

}

public class TestProxy {

    @Test
    public void test01(){
        //被代理类的对象
        RealSubject2 real = new RealSubject2();
        //创建了一个实现了InvocationHandler接口的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        //调用blind()方法，动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象
        Object obj = handler.blind(real);
        //此时sub就是代理类的对象
        Subject sub = (Subject) obj;
        //转到对InvocationHandler接口的实现类的invoke()方法的调用
        sub.action();

        int count = sub.count();
        System.out.println(count);

        //例子
        NickClothFactory nick = new NickClothFactory();
        //获取代理类的对象
        ClothFactory proxyCloth = (ClothFactory) handler.blind(nick);
        proxyCloth.productCloth();
    }

}
